/**
 * Copyright(c) 2013 Jade Techonologies Co., Ltd.
 *
 * History:
 *   13-4-28 下午2:30 Created by dwzhang
 */
package com.jade.framework.base.net;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;

import com.jade.framework.base.JadeSystem;
import org.apache.commons.collections.CollectionUtils;

/**
 * 网络地址工具类。
 *
 * @author dwzhang
 * @version 1.0 13-4-28 下午2:30
 */
public class InetAddressUtils
{
    private static InetAddress localAddress;
    private static InetAddress localHost;
    private static InetAddress[] netInterfaces;
    public static InetAddress ZERO;
    private static Map<String, InetAddress> ip2Address = null;
    private static final String KEY_LOCAL_HOST = "jade.system.address";

    static {
        try {
            ZERO = InetAddress.getByName("0.0.0.0");

            initInterfaces();

            localHost = InetAddress.getByName("127.0.0.1");

            String host = JadeSystem.getProperty(KEY_LOCAL_HOST);
            if (host == null) {
                try {
                    localAddress = InetAddress.getLocalHost();
                }
                catch (Exception e) {
                    localAddress = localHost;
                }
            }
            else {
                localAddress = InetAddress.getByName(host);
                if (!isLocalAddress(localAddress)) {
                    System.err.println("The ip address:" + host + " is not a valid network interface.");
                    System.exit(-1);
                }
            }
        }
        catch (Exception e) {
            JadeSystem.getLog().error("Init InetAddressUtil exception", e);
        }
    }

    private static void initInterfaces()
            throws Exception
    {
        Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
        List<InetAddress> list = new ArrayList<InetAddress>();
        while (en.hasMoreElements()) {
            NetworkInterface ni = en.nextElement();
            CollectionUtils.addAll(list, ni.getInetAddresses());
        }
        netInterfaces = new InetAddress[list.size()];
        list.toArray(netInterfaces);

        ip2Address = new HashMap<String, InetAddress>();

        for (InetAddress netInterface : netInterfaces) {
            ip2Address.put(netInterface.getHostAddress(), netInterface);
        }
    }

    /**
     * 根据IP地址返回地址
     *
     * @param ip IP地址
     */
    public static InetAddress getAddress(String ip)
    {
        return (InetAddress)ip2Address.get(ip);
    }

    /** 返回所有网卡上的所有绑定IP，这个方法只在JDK1.4下有效 */
    public static InetAddress[] getNetInterfaces()
    {
        return netInterfaces;
    }

    /** 本地地址，跟HostPort中返回的地址一样 */
    public static InetAddress getLocalAddress()
    {
        if (localAddress != null) {
            return localAddress;
        }

        if (netInterfaces == null) {
            return localHost;
        }
        for (int i = 0; i < netInterfaces.length; i++) {
            String address = netInterfaces[i].getHostAddress();
            if (!"127.0.0.1".equals(address)) {
                return localAddress = netInterfaces[i];
            }
        }
        return localHost;
    }

    /**
     * 判断是否属于本地的IP地址
     *
     * @param address 地址
     */
    public static boolean isLocalAddress(InetAddress address)
    {
        return isLocalAddress(address.getHostAddress());
        //        if (address == null) {
        //            return false;
        //        }
        //        else if (localHost.equals(address) || ZERO.equals(address)) {
        //            return true;
        //        }
        //        if (netInterfaces == null) {
        //            return true;
        //        }
        //        for (int i = 0; i < netInterfaces.length; i++) {
        //            if (netInterfaces[i].equals(address)) {
        //                return true;
        //            }
        //        }
        //        return false;
    }

    public static boolean isLocalAddress(String address)
    {
        if (address == null) {
            return false;
        }
        else if (localHost.getHostAddress().equals(address) || ZERO.getHostAddress().equals(address)) {
            return true;
        }
        if (netInterfaces == null) {
            return true;
        }
        for (int i = 0; i < netInterfaces.length; i++) {
            if (netInterfaces[i].getHostAddress().equals(address)) {
                return true;
            }
        }
        return false;
    }
}
